#include "ueq_serial.h"

void ueq_serial_rx_init(
    UeqSerialRx            *serial,
    UeqEventQueue          *event_queue,
    UeqSerialRxByteFunc     rx_byte_func,
    UeqEvent                event,
    BYTE                   *buffer,
    INT32                   buffer_size)
{
    UEQ_ASSERT(serial != NULL);
    UEQ_ASSERT(event_queue != NULL);
    UEQ_ASSERT(rx_byte_func != NULL);
    UEQ_ASSERT(buffer != NULL);
    serial->event_queue = event_queue;
    serial->rx_byte_func = rx_byte_func;
    serial->event = event;
    ueq_fifo_init(&serial->buffer, buffer, buffer_size);
}

void ueq_serial_tx_init(
    UeqSerialTx            *serial,
    UeqEventQueue          *event_queue,
    UeqSerialTxByteFunc     tx_byte_func,
    UeqEvent                event,
    BYTE                   *buffer,
    INT32                   buffer_size)
{
    UEQ_ASSERT(serial != NULL);
    UEQ_ASSERT(event_queue != NULL);
    UEQ_ASSERT(tx_byte_func != NULL);
    UEQ_ASSERT(buffer != NULL);
    serial->event_queue = event_queue;
    serial->tx_byte_func = tx_byte_func;
    serial->event = event;
    ueq_fifo_init(&serial->buffer, buffer, buffer_size);
}

void ueq_serial_rx_isr_handler(UeqSerialRx *serial)
{
    UEQ_ASSERT(serial != NULL);
    if (ueq_fifo_is_full(&serial->buffer) == FALSE)
    {
        BYTE data = (*serial->rx_byte_func)();
        ueq_fifo_push_back(&serial->buffer, data);
        if (ueq_event_queue_contains(serial->event_queue, serial->event) == FALSE)
        {
            ueq_event_queue_push_back(serial->event_queue, serial->event);
        }
    }
}

void ueq_serial_tx_isr_handler(UeqSerialTx *serial)
{
    UEQ_ASSERT(serial != NULL);
    if (ueq_fifo_is_empty(&serial->buffer) == FALSE)
    {
        BYTE data = ueq_fifo_pop_front(&serial->buffer);
        (*serial->tx_byte_func)(data);
    }
}

void ueq_serial_tx_write(UeqSerialTx *serial, BYTE *buffer, INT32 size)
{
    UEQ_ASSERT(serial != NULL);
    UEQ_ASSERT(buffer != NULL);
    if (ueq_fifo_write(&serial->buffer, buffer, size))
    {
        if (!serial->is_transmitting)
        {
            BYTE data = ueq_fifo_pop_front(&serial->buffer);
            (*serial->tx_byte_func)(data);
        }
    }
}
